/*
 * Copyright (C) 2009 Rafael Fernandes
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonebooksharing.android.activities.wishlist;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import com.phonebooksharing.android.widgets.view.CrossableItem;
import com.phonebooksharing.dto.gallery.WishlistItem;

public class WishlistSearchHandler {

    private static final String SNIPPETS_FEED = "http://base.google.com/base/feeds/snippets";

    private static final String QUERY_SUFFIX  = " [item type : products]";

    public static ArrayList<CrossableItem<WishlistItem>> searchProducts(String qry) throws IOException, SAXException, ParserConfigurationException {
        /*
         * Create a URL object, open an Http connection on it and get the input
         * stream that reads the Http response.
         */
        URL url = new URL(SNIPPETS_FEED + "?bq=" + URLEncoder.encode(qry + QUERY_SUFFIX, "UTF-8"));
        HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
        InputStream inputStream = httpConnection.getInputStream();

        ArrayList<CrossableItem<WishlistItem>> results = new ArrayList<CrossableItem<WishlistItem>>();

        /*
         * Create a SAX XML parser and pass in the input stream to the parser.
         * The parser will use DisplayTitleHandler to extract the titles from
         * the XML stream.
         */
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser = factory.newSAXParser();
        parser.parse(inputStream, new DisplayTitlesHandler(results));
        
        return results;
    }

    private static class DisplayTitlesHandler extends DefaultHandler {
        private ArrayList<CrossableItem<WishlistItem>> results;

        DisplayTitlesHandler(ArrayList<CrossableItem<WishlistItem>> results) {
            this.results = results;
        }

        /**
         * Stack containing the opening XML tags of the response.
         */
        private Stack<String> xmlTags = new Stack<String>();

        /**
         * True if we are inside of a data entry's title, false otherwise.
         */
        private boolean       title   = false, price = false, img = false, url = false, author = false, id = false;

        private WishlistItem  wish;

        /**
         * Receive notification of an opening XML tag: push the tag to
         * <code>xmlTags</code>. If the tag is a title tag inside an entry tag,
         * turn <code>insideEntryTitle</code> to <code>true</code>.
         */
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            if ((localName.equals("entry") || qName.equals("entry"))) {
                wish = new WishlistItem();
            } else if ((localName.equals("id") || qName.equals("g:id")) && 
                    "text".equals(attributes.getValue("type")) && 
                    xmlTags.peek().equals("entry")) {
                id = true;
            } else if ((localName.equals("title") || qName.equals("title")) && xmlTags.peek().equals("entry")) {
                title = true;
            } else if ((localName.equals("price") || qName.equals("g:price")) && xmlTags.peek().equals("entry")) {
                price = true;
            } else if ((localName.equals("image_link") || qName.equals("g:image_link")) && xmlTags.peek().equals("entry")) {
                img = true;
            } else if ((localName.equals("link") || qName.equals("g:link")) && 
                    "alternate".equals(attributes.getValue("rel")) && 
                    xmlTags.peek().equals("entry")) {
                url = true;
                wish.prodUrl = attributes.getValue("href");
            } else if ((localName.equals("author") || qName.equals("g:auhtor")) && xmlTags.peek().equals("entry")) {
                author = true;
            }

            xmlTags.push(localName);
        }

        /**
         * Receive notification of a closing XML tag: remove the tag from teh
         * stack. If we were inside of an entry's title, turn
         * <code>insideEntryTitle</code> to <code>false</code>.
         */
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            // If a "title" element is closed, we start a new line, to prepare
            // printing the new title.

            if (xmlTags.peek().equals("entry")) {// new item
                results.add(new CrossableItem<WishlistItem>(wish));
            }

            xmlTags.pop();
            if (title) {
                title = false;
            } else if (price) {
                price = false;
            } else if (img) {
                img = false;
            } else if (url) {
                url = false;
            } else if(author) {
                author = false;
            } else if(id) {
                id = false;
            }
        }

        /**
         * Callback method for receiving notification of character data inside
         * an XML element.
         */
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            // display the character data if the opening tag is "title" and its
            // parent is
            // "entry"
            if (title) {
                wish.prodName = new String(ch, start, length);
            } else if (price) {
                wish.prodPrice = new String(ch, start, length);
            } else if (img) {
                wish.prodImgUrl = new String(ch, start, length);
            } else if (url) {
//                wish.prodUrl = new String(ch, start, length);
            } else if (author) {
                wish.prodAuthor = new String(ch, start, length);
            } else if (id) {
                wish.prodID = new String(ch, start, length);
            }
        }
    }
}
